package bancosys.tec.security.impl.services.incluir;

import java.util.Collection;
import java.util.List;

import jmine.tec.di.annotation.Injected;
import jmine.tec.services.annotations.Execution;
import jmine.tec.services.annotations.Input;
import jmine.tec.services.annotations.ServiceImplementor;
import jmine.tec.services.annotations.WithPreffix;
import jmine.tec.services.api.ActionsEnum;
import jmine.tec.utils.collection.MultiMap;
import jmine.tec.utils.collection.impl.ListMultiMap;
import bancosys.tec.security.impl.dao.CredentialDAO;
import bancosys.tec.security.impl.domain.Credential;
import bancosys.tec.security.impl.domain.Group;
import bancosys.tec.security.impl.domain.MetaCredential;

/**
 * @author bruno.ozahata
 * @created Jun 6th, 2012
 */
@ServiceImplementor(action = ActionsEnum.INCLUIR)
public class MetaCredentialGroupAssociationService {

    public static final String GROUP = "Group";

    public static final String META_CREDENTIAL = "Meta Credential";

    private Group group;

    private List<MetaCredential> metaCredentials;

    private MultiMap<MetaCredential, Credential> cache = new ListMultiMap<MetaCredential, Credential>();

    private CredentialDAO credentialDAO;

    /**
     * Execute the service
     */
    @Execution
    public void execute() {
        this.indexCredentials();
        this.addMetaCredentials();
        this.group.getPersister().save();
    }

    /**
     * Add {@link MetaCredential} in {@link Group}
     */
    private void addMetaCredentials() {
        for (MetaCredential meta : this.metaCredentials) {
            Collection<? extends Credential> cachedCredentials = this.cache.get(meta);
            if (cachedCredentials != null) {
                for (Credential credential : cachedCredentials) {
                    this.group.addCredential(credential);
                }
            }
        }
    }

    /**
     * Index {@link Credential} by {@link MetaCredential}
     */
    private void indexCredentials() {
        List<Credential> credentials = this.credentialDAO.findAll();
        for (Credential credential : credentials) {
            if (credential.getMetaCredential() != null) {
                this.cache.add(credential.getMetaCredential(), credential);
            }
        }
    }

    /**
     * @param group the group to set
     */
    @Input(fieldName = GROUP, required = true)
    public void setGroup(Group group) {
        this.group = group;
    }

    /**
     * @param metaCredentials the metaCredentials to set
     */
    @WithPreffix(preffix = META_CREDENTIAL, required = true)
    public void setMetaCredentials(List<MetaCredential> metaCredentials) {
        this.metaCredentials = metaCredentials;
    }

    /**
     * @param credentialDAO the credentialDAO
     */
    @Injected
    public void setCredentialDAO(CredentialDAO credentialDAO) {
        this.credentialDAO = credentialDAO;
    }

}
